/* @flow */

import config from '../config';
import { initUse } from './use';
import { initMixin } from './mixin';
import { initExtend } from './extend';
import { initAssetRegisters } from './assets';
import { set, del } from '../observer/index';
import { ASSET_TYPES } from 'shared/constants';
// keep-alive组件
import builtInComponents from '../components/index';
import { observe } from 'core/observer/index';

import { warn, extend, nextTick, mergeOptions, defineReactive } from '../util/index';

export function initGlobalAPI(Vue: GlobalAPI) {
    // config
    const configDef = {};
    configDef.get = () => config;
    // 如果当前环境为开发环境，给configDef增加 set 方法
    if (process.env.NODE_ENV !== 'production') {
        configDef.set = () => {
            // 请勿替换Vue.config对象，请设置单独的字段
            warn('Do not replace the Vue.config object, set individual fields instead.');
        };
    }
    // 初始化 Vue.config 对象(platforms/web/index 对config对象进行赋值)
    Object.defineProperty(Vue, 'config', configDef);

    // exposed util methods.
    // NOTE: these are not considered part of the public API - avoid relying on
    // them unless you are aware of the risk.
    // 这些工具方法不视作全局API的一部分，除非你已经意识到某些风险，否则不要去依赖他们
    Vue.util = {
        warn,
        extend,
        mergeOptions,
        defineReactive
    };
    // 静态方法 set/delete/nextTick
    Vue.set = set;
    Vue.delete = del;
    Vue.nextTick = nextTick;

    // 2.6 explicit observable API
    // 让一个对象可响应
    Vue.observable = <T>(obj: T): T => {
        observe(obj);
        return obj;
    };
    // 初始化 Vue.options 对象，并给其扩展
    // components 全局组件/directives全局指令/filters 全局过滤器
    Vue.options = Object.create(null);
    ASSET_TYPES.forEach(type => {
        Vue.options[type + 's'] = Object.create(null);
    });

    // this is used to identify the "base" constructor to extend all plain-object
    // components with in Weex's multi-instance scenarios.
    // 把当前的Vue实例记录到Vue.options._base上
    Vue.options._base = Vue;
    // 设置 keep-alive 组件
    extend(Vue.options.components, builtInComponents);

    // 注册 Vue.use() 用来注册插件
    initUse(Vue);
    // 注册 Vue.mixin() 实现混入。mixin注册的为全局的options
    initMixin(Vue);
    // 注册 Vue.extend() 基于传入的options返回一个组件的构造函数。Vue.extend()返回一个自定义组件的构造函数。
    initExtend(Vue);
    // 注册 Vue.directive()、 Vue.component()、Vue.filter()
    initAssetRegisters(Vue);
}
